﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace WebSlices
{
    /// <summary>
    /// Provides static helper methods to aid web slice development.
    /// </summary>
    public static class WebSliceHelper
    {
        /// <summary>
        /// Sets the web slice discovery mode of the <paramref name="page"/>.
        /// </summary>
        /// <param name="page">The page whose discovery mode is to be set.</param>
        /// <param name="mode">The discovery mode to be set.</param>
        public static void SetWebSliceDiscoveryMode(this Page page, WebSliceDiscoveryMode mode)
        {
            if (page.Header == null)
            {
                throw new HttpException("Web slice discovery may only be configured when the page's <head> has the runat=\"server\" attribute.");
            }

            const string DiscoveryModeKey = "SliceDiscoveryMode";

            if (page.Items[DiscoveryModeKey] == null && mode == WebSliceDiscoveryMode.On)
            {
                return;
            }

            HtmlMeta meta;

            if (page.Items[DiscoveryModeKey] == null)
            {
                meta = new HtmlMeta();
                meta.Name = "slice";
                meta.Scheme = "IE";
                meta.Content = "off";
                page.Header.Controls.Add(meta);
                page.Items.Add(DiscoveryModeKey, meta);
            }
            else
            {
                if (mode == WebSliceDiscoveryMode.On)
                {
                    meta = page.Items[DiscoveryModeKey] as HtmlMeta;

                    if (meta != null)
                    {
                        meta.Parent.Controls.Remove(meta);
                        page.Items.Remove(DiscoveryModeKey);
                    }
                }
            }
        }

        /// <summary>
        /// Sets the specified <paramref name="slice"/> as the default web slice on the page.
        /// </summary>
        /// <typeparam name="TWebSlice">The type of web slice control to set as the default on the page.</typeparam>
        /// <param name="page">The <see cref="Page"/> that owns the <paramref name="slice"/>.</param>
        /// <param name="slice">The slice that should be set as the default.</param>
        /// <remarks>
        /// <para>This method should be used when there are several web slices on a page and the developer wishes to specify which one is the default.</para>
        /// </remarks>
        public static void SetDefaultWebSlice<TWebSlice>(this Page page, TWebSlice slice) where TWebSlice : Control, IWebSlice
        {
            if (slice == null)
            {
                throw new ArgumentNullException("slice");
            }

            if (page.Header == null)
            {
                throw new HttpException("A default web slice may only be specified when the page's <head> has the runat=\"server\" attribute.");
            }

            const string WebSliceKey = "DefaultSlice";

            if (page.Items[WebSliceKey] == null)
            {
                HtmlLink defaultSlice = new HtmlLink();
                defaultSlice.Href = string.Concat(page.Request.Url.GetLeftPart(UriPartial.Path), "#", ((IWebSlice)slice).Id);
                defaultSlice.Attributes["rel"] = "default-slice";
                defaultSlice.Attributes["type"] = "application/x-hatom";

                page.Header.Controls.Add(defaultSlice);

                page.Items[WebSliceKey] = defaultSlice;
            }
            else
            {
                HtmlLink current = page.Items[WebSliceKey] as HtmlLink;

                if (current != null)
                {
                    current.Href = string.Concat(page.Request.Url.GetLeftPart(UriPartial.Path), "#", ((IWebSlice)slice).Id);
                }
            }
        }
    }

    /// <summary>
    /// Defines the modes that web slice discovery can be in on a web page.
    /// </summary>
    public enum WebSliceDiscoveryMode
    {
        /// <summary>
        /// Web slice discovery is enabled for the <see cref="Page"/>.
        /// </summary>
        On,
        /// <summary>
        /// Web slice discovery is disabled for the <see cref="Page"/>.
        /// </summary>
        Off
    }
}
